package com.github.livebase.log;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Date;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

public class FileRefresher extends Thread {
    private static volatile FileRefresher refresher;
    static final FileRefresher singleton() {
        if (null == refresher) {
            synchronized (FileRefresher.class) {
                if (null == refresher) {
                    refresher = new FileRefresher();
                    refresher.setDaemon(true);
                    refresher.start();
                }
            }
        }
        return refresher;
    }
        private class LogDetail{
            String file;
            Date date;
            String threadName;
            String levelName;
            String tag;
            String message;

            private LogDetail(String file, Date date, String threadName, String levelName, String tag, String message) {
                this.file = file;
                this.date = date;
                this.threadName = threadName;
                this.levelName = levelName;
                this.tag = tag;
                this.message = message;
            }
        }
        private BlockingQueue<LogDetail> cache;
        private RandomAccessFile file;
        private String path;
        private volatile boolean isRunning;
        public FileRefresher() {
            super();
            cache = new LinkedBlockingDeque<>();
        }

        public void enQueue(String file, Date date, String threadName, String levelName, String tag, String message) {
            // 停止运行后不再接收
            if (!isRunning) {
                return ;
            }
            // 队列满后丢弃日志信息
            if (cache.remainingCapacity() != 0) {
                cache.offer(new LogDetail(file, date, threadName, levelName, tag, message));
            }
        }

        public boolean isRunning() {
            return isRunning;
        }

        @Override
        public void run() {
            isRunning = true;
            while (!Thread.interrupted()) {
                try {
                    LogDetail d = cache.take();
                    write(d);
                } catch (InterruptedException e) {

                }
            }

            isRunning = false;
            // 将剩余数据写入文件
            while (!cache.isEmpty()) {
                LogDetail d = cache.poll();
                write(d);
            }
            try {
                file.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        private RandomAccessFile getFile(LogDetail d) throws IOException {
            if (!d.file.equals(path)) {
                RandomAccessFile temp = new RandomAccessFile(d.file, "rw");
                if (file != null) {
                    file.close();
                }
                file = temp;
                file.seek(file.length());
                path = d.file;
            }
            return file;
        }
        private void write(LogDetail d) {
            try {
                RandomAccessFile file = getFile(d);
                String s = String.format("%tF %<tT.%<tL %s %s %s %s\r\n", d.date, d.threadName, d.tag, d.levelName, d.message);
                file.writeUTF(s);
            } catch (IOException e) {
                isRunning = false;
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    }